package com.tools.middle.redis.client;

import com.fasterxml.jackson.core.type.TypeReference;
import com.tools.common.container.AbsOwnList;
import com.tools.common.container.OwnPairs;
import com.tools.common.container.RowKit;
import com.tools.common.object.C;
import com.tools.common.object.json.JsonKit;
import com.tools.common.object.Note;
import com.tools.common.object.ObjKit;
import com.tools.common.object.string.VerifyKit;
import com.tools.common.thread.Timeunit;
import redis.clients.jedis.*;
import redis.clients.jedis.params.ZAddParams;
import redis.clients.jedis.params.ZIncrByParams;

import java.util.*;

/**
 * JedisCluster 集群客户端
 * 的重载操作方法的抽象实现
 * */
@Note("JedisCluster 集群客户端的重载操作方法的抽象实现")
abstract class AbsJedisCluster implements AutoCloseable {

    AbsJedisCluster() {}

    @Note("获取 JedisCluster 集群客户端实例")
    public abstract JedisCluster jedisCluster();

    @Note("关闭 Jedis 集群客户端实例")
    @Override
    public abstract void close();


    /* **********************************************************************************
     *
     *          Key 的操作方法
     *
     * *********************************************************************************
     * */

    @Note("Redis的 ttl 命令，返回该 key 的剩余过期时间，单位为秒")
    public long ttl(String key) {
        DataTypeKit.default_checkKey(key);
        Long ttl = this.jedisCluster().ttl(key);
        return DataTypeKit.default_returnTimeResult(ttl);
    }

    @Note("给指定的 key 设置过期时间，单位为秒")
    public long expired(String key, long seconds) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().expire(key, seconds);
        return DataTypeKit.default_returnTimeResult(result);
    }

    public long expired(String key, long expiration, Timeunit timeunit) {
        DataTypeKit.default_checkTimeunit(timeunit);
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().expire(key, Timeunit.toSecond(expiration, timeunit));
        return DataTypeKit.default_returnTimeResult(result);
    }

    @Note("删除指定的 key-value")
    public long del(String key) {
        DataTypeKit.default_checkKey(key);
        Long delResult = this.jedisCluster().del(key);
        return DataTypeKit.default_returnResultLong(delResult);
    }

    public long del(String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Long delResult = this.jedisCluster().del(keys);
        return DataTypeKit.default_returnResultLong(delResult);
    }

    public long del(Iterable<String> keys) {
        Long delResult = this.jedisCluster().del(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_returnResultLong(delResult);
    }
    

    @Note("替换 key 的名称")
    public String rename(String oldKey, String newKey) {
        DataTypeKit.default_checkKey(oldKey);
        DataTypeKit.default_checkKey(newKey);
        return this.jedisCluster().rename(oldKey, newKey);
    }

    /* **********************************************************************************
     *
     *           字符串
     *
     * *********************************************************************************
     * */

    public String set(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().set(key, ObjKit.toStringEmptyString(value));
    }

    public String setex(String key, long seconds, Object value) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().setex(key, seconds, ObjKit.toStringEmptyString(value));
    }

    public String setex(String key, long expiration, Timeunit timeunit, Object value) {
        DataTypeKit.default_checkTimeunit(timeunit);
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().setex(key, Timeunit.toSecond(expiration, timeunit), ObjKit.toStringEmptyString(value));
    }

    @Note("如果不存在就 set")
    public long setnx(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().setnx(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("返回 value 的 length")
    public long strlen(String key) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().strlen(key);
        return DataTypeKit.default_returnResultLong(result);
    }

    public Object get(String key) {
        DataTypeKit.default_checkKey(key);
        String result = this.jedisCluster().get(key);
        return ObjKit.stringToRealValue(result, true);
    }

    public <T> T get(String key, Class<T> targetType) {
        DataTypeKit.default_checkKey(key);
        String result = this.jedisCluster().get(key);
        return JsonKit.toEntity(result, targetType);
    }

    public <T> T get(String key, TypeReference<T> targetType) {
        DataTypeKit.default_checkKey(key);
        String result = this.jedisCluster().get(key);
        return JsonKit.toEntity(result, targetType);
    }

    public <T> T get(String key, C<T> targetType) {
        DataTypeKit.default_checkKey(key);
        String result = this.jedisCluster().get(key);
        return (T) ObjKit.toRealValue(result, targetType);
    }

    @Note("如果 key 不存在就 set 新值 newValue，然后返回 newValue。存在则返回旧值")
    public Object getSet(String key, Object newValue) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().getSet(key, ObjKit.toStringEmptyString(newValue));
        return ObjKit.stringToRealValue(res, true);
    }

    public <T> T getSet(String key, Object newValue, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().getSet(key, ObjKit.toStringEmptyString(newValue));
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T getSet(String key, Object newValue, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String result = this.jedisCluster().getSet(key, ObjKit.toStringEmptyString(newValue));
        return JsonKit.toEntity(result, valueType);
    }

    public <T> T getSet(String key, Object newValue, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String result = this.jedisCluster().getSet(key, ObjKit.toStringEmptyString(newValue));
        return (T) ObjKit.stringToRealValue(result, valueType);
    }

    public List<Object> mget(String... keys) {
        DataTypeKit.default_checkKeys(keys);
        List<String> res = this.jedisCluster().mget(keys);
        return DataTypeKit.default_asObjectList(res);
    }

    public <T> List<T> mget(Class<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        List<String> res = this.jedisCluster().mget(keys);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    public <T> List<T> mget(C<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        List<String> res = this.jedisCluster().mget(keys);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    public List<Object> mget(Iterable<String> keys) {
        String[] keyArray = DataTypeKit.default_asStringKeyArray(keys);
        List<String> res = this.jedisCluster().mget(keyArray);
        return DataTypeKit.default_asObjectList(res);
    }

    public <T> List<T> mget(Class<T> valueType, Iterable<String> keys) {
        String[] keyArray = DataTypeKit.default_asStringKeyArray(keys);
        List<String> res = this.jedisCluster().mget(keyArray);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    public <T> List<T> mget(C<T> valueType, Iterable<String> keys) {
        String[] keyArray = DataTypeKit.default_asStringKeyArray(keys);
        List<String> res = this.jedisCluster().mget(keyArray);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }


    public Map<String, Object> mgetAsMap(String... keys) {
        DataTypeKit.default_checkKeys(keys);
        List<String> res = this.jedisCluster().mget(keys);
        return DataTypeKit.default_hashResultAsMap(keys, res);
    }

    public Map<String, Object> mgetAsMap(Iterable<String> keys) {
        String[] keyArray = DataTypeKit.default_asStringKeyArray(keys);
        List<String> res = this.jedisCluster().mget(keyArray);
        return DataTypeKit.default_hashResultAsMap(keyArray, res);
    }

    public String mset(Map<String, Object> keyAndValue) {
        String[] param = DataTypeKit.default_asKeyValueStringArray(keyAndValue);
        return this.jedisCluster().mset(param);
    }

    public String mset(OwnPairs<String, Object> keyAndValue) {
        String[] param = DataTypeKit.default_asKeyValueStringArray(keyAndValue);
        return this.jedisCluster().mset(param);
    }

    public String mset(Object javaBean) {
        if(javaBean == null) throw new NullPointerException("JavaBean 对象为 null");
        Map<String, Object> map = ObjKit.allFieldValue(javaBean);
        return this.mset(map);
    }

    public String mset(String jsonObject) {
        if(!VerifyKit.isJsonObject(jsonObject)) throw new IllegalArgumentException(jsonObject + " 不是对象类型的 JSON 字符串");
        Map<String, Object> map = JsonKit.toEntity(jsonObject,
                new TypeReference<HashMap<String, Object>>() {});
        return this.mset(map);
    }

    @Note("游标 cursor 的初始值为【0】，当返回的游标值再度为【0】 时才代表整体遍历结束" +
            "返回值是批量的 key 和下一次开始游标。" +
            "返回的结果可能会有重复，需要自己去重" +
            "ScanParams 是可以设置 count（返回 key 的个数）和 match（正则匹配）的")
    public ScanResult<String> scan(String cursor, ScanParams params) {
        if(params == null) throw new NullPointerException("ScanParams 参数不能为 null");
        if(cursor == null || cursor.isEmpty()) cursor = "0";
        return this.jedisCluster().scan(cursor, params);
    }
    
    public ScanResult<String> scan(String cursor, ScanParams params, String type) {
        if(cursor == null || cursor.isEmpty()) cursor = "0";
        if(params == null) throw new NullPointerException("ScanParams 参数不能为 null");
        if(type == null || type.isEmpty()) return scan(cursor, params);
        return this.jedisCluster().scan(cursor, params, type);
    }


    @Note("执行 lua 脚本。可使 redis 的多个操作为原子性操作。只处理单个 key")
    public Object eval(String luaScript, String key) {
        DataTypeKit.default_checkLuaScriptIsNotEmpty(luaScript);
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().eval(luaScript, key);
    }

    @Note("执行 lua 脚本。参数是告诉 redis 从 0 到 keyCount 个参数是 key，剩余的全是参数")
    public Object eval(String luaScript, int keyCount, Object... args) {
        DataTypeKit.default_checkLuaScriptIsNotEmpty(luaScript);
        String[] keyAndArgs = DataTypeKit.default_asStringArray(args);
        return this.jedisCluster().eval(luaScript, keyCount, keyAndArgs);
    }

    @Note("执行 lua 脚本。参数是告诉 redis 从 0 到 keyCount 个参数是 key，剩余的全是参数")
    public Object eval(String luaScript, int keyCount, List args) {
        DataTypeKit.default_checkLuaScriptIsNotEmpty(luaScript);
        String[] keyAndArgs = DataTypeKit.default_asStringArray(args);
        return this.jedisCluster().eval(luaScript, keyCount, keyAndArgs);
    }

    @Note("执行 lua 脚本。参数是告诉 redis 从 0 到 keyCount 个参数是 key，剩余的全是参数")
    public Object eval(String luaScript, int keyCount, AbsOwnList args) {
        DataTypeKit.default_checkLuaScriptIsNotEmpty(luaScript);
        String[] keyAndArgs = DataTypeKit.default_asStringArray(args);
        return this.jedisCluster().eval(luaScript, keyCount, keyAndArgs);
    }


    @Note("执行 lua 脚本，返回值可能是【String、Long、List<Object>、null" +
            "或 【布尔值的（0 或 1，也是用 Long 接收）】")
    public Object eval(String luaScript, List<String> keys, List args) {
        DataTypeKit.default_checkLuaScriptIsNotEmpty(luaScript);
        List<String> params = new ArrayList<>(args.size());
        DataTypeKit.default_copyToStringCollection(params, args);
        return this.jedisCluster().eval(luaScript, keys, params);
    }

    public Object eval(String luaScript, String[] keys, Object... args) {
        DataTypeKit.default_checkLuaScriptIsNotEmpty(luaScript);
        List<String> keyArray = RowKit.toArrayList(keys);
        List<String> params = new ArrayList<>(args.length);
        DataTypeKit.default_copyToStringCollection(params, args);
        return this.jedisCluster().eval(luaScript, keyArray, params);
    }


    public Object eval(String luaScript, AbsOwnList<String> keys, AbsOwnList args) {
        DataTypeKit.default_checkLuaScriptIsNotEmpty(luaScript);
        List<String> params = new ArrayList<>(args.size());
        DataTypeKit.default_copyToStringCollection(params, args);
        return this.jedisCluster().eval(luaScript, keys.toList(), params);
    }

    /* **********************************************************************************
     *
     *          List 列表类型 - 操作方法
     *
     * *********************************************************************************
     * */

    public long lpush(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().lpush(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long lpush(String key, Object... values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().lpush(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long lpush(String key, Iterable values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().lpush(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }


    public List<Object> lrange(String key, long start, long stop) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().lrange(key, start, stop);
        return DataTypeKit.default_asObjectList(res);
    }


    public <T> List<T> lrange(String key, long start, long stop, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().lrange(key, start, stop);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }


    public <T> List<T> lrange(String key, long start, long stop, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().lrange(key, start, stop);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }


    public <T> List<T> lrange(String key, long start, long stop, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().lrange(key, start, stop);
        List<T> result = new ArrayList<>(res.size());
        for (String s : res) {
            result.add(JsonKit.toEntity(s, valueType));
        }
        return result;
    }


    public Object lpop(String key) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().lpop(key);
        return ObjKit.stringToRealValue(res, true);
    }

    public <T> T lpop(String key, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().lpop(key);
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T lpop(String key, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().lpop(key);
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T lpop(String key, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().lpop(key);
        return JsonKit.toEntity(res, valueType);
    }

    public List<Object> lpop(String key, int count) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().lpop(key, count);
        return DataTypeKit.default_asObjectList(res);
    }

    public <T> List<T> lpop(String key, int count, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().lpop(key, count);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    public <T> List<T> lpop(String key, int count, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().lpop(key, count);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    public <T> List<T> lpop(String key, int count, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().lpop(key, count);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    @Note("返回列表中指定索引的值")
    public Object lindex(String key, long index) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().lindex(key, index);
        return ObjKit.stringToRealValue(res, true);
    }

    public <T> T lindex(String key, long index, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().lindex(key, index);
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T lindex(String key, long index, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().lindex(key, index);
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T lindex(String key, long index, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().lindex(key, index);
        return (T) ObjKit.stringToRealValue(res, valueType);
    }

    @Note("列表存在时，从头部插入元素")
    public long lpushx(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().lpushx(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("列表存在时，从头部插入所有元素")
    public long lpushx(String key, Object... newValues) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().lpushx(key, DataTypeKit.default_asStringArray(newValues));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long lpushx(String key, Iterable newValues) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().lpushx(key, DataTypeKit.default_asStringArray(newValues));
        return DataTypeKit.default_returnResultLong(result);
    }

    public String lset(String key, long index, Object value) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().lset(key, index, ObjKit.toStringEmptyString(value));
    }

    @Note("返回列表的长度")
    public long llen(String key) {
        DataTypeKit.default_checkKey(key);
        Long length = this.jedisCluster().llen(key);
        return DataTypeKit.default_returnResultLong(length);
    }

    @Note("让列表保留指定区间的内容，其余的全部删除")
    public String ltrim(String key, long start, long stop) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().ltrim(key, start, stop);
    }

    @Note("将 value 插入到 pivot 之前还是之后的位置")
    public long linsert(String key, ListPosition position, Object pivot, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().linsert(key, position,
                ObjKit.toStringEmptyString(pivot),
                ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("删除列表与 removeValue 相同的 value，count 为删除个数，为 0 则移除全部与之相同的 value")
    public long lrem(String key, Object removeValue, long count) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().lrem(key, count, ObjKit.toStringEmptyString(removeValue));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long rpush(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().rpush(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long rpush(String key, Object... values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().rpush(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }


    public long rpush(String key, Iterable values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().rpush(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }

    public Object rpop(String key) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().rpop(key);
        return ObjKit.stringToRealValue(res, true);
    }

    public <T> T rpop(String key, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().rpop(key);
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T rpop(String key, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().rpop(key);
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T rpop(String key, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().rpop(key);
        return (T) ObjKit.stringToRealValue(res, valueType);
    }

    public List<Object> rpop(String key, int count) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().rpop(key, count);
        return DataTypeKit.default_asObjectList(res);
    }

    public <T> List<T> rpop(String key, int count, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().rpop(key, count);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    public <T> List<T> rpop(String key, int count, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().rpop(key, count);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    public <T> List<T> rpop(String key, int count, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().rpop(key, count);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }


    public long rpushx(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().rpushx(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long rpushx(String key, Object... values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().rpushx(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long rpushx(String key, Iterable values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().rpushx(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }


    /* **********************************************************************************
     *
     *          哈希 Hash 类型 - 操作方法
     *
     * *********************************************************************************
     * */

    public long hset(String key, String field, Object value) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKey(field);
        Long result = this.jedisCluster().hset(key, field, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long hsetnx(String key, String field, Object value) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKey(field);
        Long result = this.jedisCluster().hsetnx(key, field, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long hset(String key, Map fieldAndValues) {
        DataTypeKit.default_checkKey(key);
        Map<String, String> map = DataTypeKit.default_asStringValueMap(fieldAndValues);
        Long result = this.jedisCluster().hset(key, map);
        return DataTypeKit.default_returnResultLong(result);
    }


    public long hset(String key, OwnPairs fieldAndValues) {
        DataTypeKit.default_checkKey(key);
        Map<String, String> map = DataTypeKit.default_asStringValueMap(fieldAndValues);
        Long result = this.jedisCluster().hset(key, map);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long hset(String key, String jsonObject) {
        if(!VerifyKit.isJsonObject(jsonObject)) {
            throw new IllegalArgumentException("【"+ jsonObject +"】 不是 JSON 对象类型");
        }
        DataTypeKit.default_checkKey(key);
        HashMap<String, String> map = JsonKit.toEntity(jsonObject, new C<HashMap<String, String>>() {});
        Long result = this.jedisCluster().hset(key, map);
        return DataTypeKit.default_returnResultLong(result);
    }


    public long hset(String key, Object javaBean) {
        if(javaBean == null) throw new NullPointerException("要存储的 Java 对象为 null，无法获取其 [属性名称-属性值]");
        DataTypeKit.default_checkKey(key);
        HashMap<String, String> map = (HashMap<String, String>) ObjKit.toRealValue(javaBean, new C<HashMap<String, String>>() {});
        Long result = this.jedisCluster().hset(key, map);
        return DataTypeKit.default_returnResultLong(result);
    }


    public Object hget(String key, String field) {
        DataTypeKit.default_checkKey(key);
        String result = this.jedisCluster().hget(key, field);
        return ObjKit.stringToRealValue(result, true);
    }

    public <T> T hget(String key, String field, Class<T> targetType) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKey(field);
        String result = this.jedisCluster().hget(key, field);
        return JsonKit.toEntity(result, targetType);
    }

    public <T> T hget(String key, String field, TypeReference<T> typeReference) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKey(field);
        String result = this.jedisCluster().hget(key, field);
        return JsonKit.toEntity(result, typeReference);
    }

    public <T> T hget(String key, String field, C<T> targetType) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKey(field);
        String result = this.jedisCluster().hget(key, field);
        return (T) ObjKit.toRealValue(result, targetType);
    }

    public Map<String, Object> hgetAll(String key) {
        DataTypeKit.default_checkKey(key);
        Map<String, String> res = this.jedisCluster().hgetAll(key);
        return DataTypeKit.default_asStandardMap(res);
    }

    public <T> T hgetAll(String key, C<T> beanType) {
        DataTypeKit.default_checkKey(key);
        Map<String, String> map = this.jedisCluster().hgetAll(key);
        return (T) ObjKit.toRealValue(map, beanType);
    }

    public String hmset(String key, Map fieldAndValues) {
        DataTypeKit.default_checkKey(key);
        Map<String, String> map = DataTypeKit.default_asStringValueMap(fieldAndValues);
        return this.jedisCluster().hmset(key, map);
    }

    public String hmset(String key, OwnPairs fieldAndValues) {
        DataTypeKit.default_checkKey(key);
        Map<String, String> map = DataTypeKit.default_asStringValueMap(fieldAndValues);
        return this.jedisCluster().hmset(key, map);
    }

    public String hmset(String key, String jsonObject) {
        if(!VerifyKit.isJsonObject(jsonObject)) {
            throw new IllegalArgumentException("【"+ jsonObject +"】 不是 JSON 对象类型");
        }
        DataTypeKit.default_checkKey(key);
        HashMap<String, String> map = JsonKit.toEntity(jsonObject, new C<HashMap<String, String>>() {});
        return this.jedisCluster().hmset(key, map);
    }

    public String hmset(String key, Object javaBean) {
        if(javaBean == null) throw new NullPointerException("要存储的 Java 对象为 null，无法获取其 [属性名称-属性值]");
        DataTypeKit.default_checkKey(key);
        HashMap<String, String> map = (HashMap<String, String>) ObjKit.toRealValue(javaBean, new C<HashMap<String, String>>() {});
        return this.jedisCluster().hmset(key, map);
    }

    public List<Object> hmget(String key, String... fields) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKeys(fields);
        List<String> result = this.jedisCluster().hmget(key, fields);
        return DataTypeKit.default_asObjectList(result);
    }

    public List<Object> hmget(String key, Iterable<String> fields) {
        DataTypeKit.default_checkKey(key);
        List<String> result = this.jedisCluster().hmget(key, DataTypeKit.default_asStringKeyArray(fields));
        return DataTypeKit.default_asObjectList(result);
    }

    public <T> List<T> hmget(String key, Class<T> valueType, String... fields) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKeys(fields);
        List<String> result = this.jedisCluster().hmget(key, fields);
        return DataTypeKit.default_asSpecifyTypeList(result, valueType);
    }

    public <T> List<T> hmget(String key, Class<T> valueType, Iterable<String> fields) {
        DataTypeKit.default_checkKey(key);
        List<String> result = this.jedisCluster().hmget(key, DataTypeKit.default_asStringKeyArray(fields));
        return DataTypeKit.default_asSpecifyTypeList(result, valueType);
    }


    public <T> List<T> hmget(String key, TypeReference<T> valueType, String... fields) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKeys(fields);
        List<String> result = this.jedisCluster().hmget(key, fields);
        return DataTypeKit.default_asSpecifyTypeList(result, valueType);
    }

    public <T> List<T> hmget(String key, TypeReference<T> valueType, Iterable<String> fields) {
        DataTypeKit.default_checkKey(key);
        List<String> result = this.jedisCluster().hmget(key, DataTypeKit.default_asStringKeyArray(fields));
        return DataTypeKit.default_asSpecifyTypeList(result, valueType);
    }

    public <T> List<T> hmget(String key, C<T> valueType, String... fields) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKeys(fields);
        List<String> result = this.jedisCluster().hmget(key, fields);
        return DataTypeKit.default_asSpecifyTypeList(result, valueType);
    }

    public <T> List<T> hmget(String key, C<T> valueType, Iterable<String> fields) {
        DataTypeKit.default_checkKey(key);
        List<String> result = this.jedisCluster().hmget(key, DataTypeKit.default_asStringKeyArray(fields));
        return DataTypeKit.default_asSpecifyTypeList(result, valueType);
    }

    public Map<String, Object> hmgetAsMap(String key, String... fields) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKeys(fields);
        List<String> res = this.jedisCluster().hmget(key, fields);
        return DataTypeKit.default_hashResultAsMap(fields, res);
    }

    public Map<String, Object> hmgetAsMap(String key, List<String> fields) {
        DataTypeKit.default_checkKey(key);
        String[] fieldArray = DataTypeKit.default_asStringKeyArray(fields);
        List<String> res = this.jedisCluster().hmget(key, fieldArray);
        return DataTypeKit.default_hashResultAsMap(fieldArray, res);
    }

    public Map<String, Object> hmgetAsMap(String key, AbsOwnList<String> fields) {
        DataTypeKit.default_checkKey(key);
        String[] fieldArray = DataTypeKit.default_asStringKeyArray(fields);
        List<String> res = this.jedisCluster().hmget(key, fieldArray);
        return DataTypeKit.default_hashResultAsMap(fieldArray, res);
    }


    public <T> T hmgetAsBean(String key, C<T> beanType, String... fields) {
        Map<String, Object> map = this.hmgetAsMap(key, fields);
        return ObjKit.buildObject(beanType, map);
    }

    public <T> T hmgetAsBean(String key, C<T> beanType, List<String> fields) {
        Map<String, Object> map = this.hmgetAsMap(key, fields);
        return ObjKit.buildObject(beanType, map);
    }

    public <T> T hmgetAsBean(String key, C<T> beanType, AbsOwnList<String> fields) {
        Map<String, Object> map = this.hmgetAsMap(key, fields);
        return ObjKit.buildObject(beanType, map);
    }

    public long hdel(String key, String field) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKey(field);
        Long result = this.jedisCluster().hdel(key, field);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long hdel(String key, String... fields) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKeys(fields);
        Long result = this.jedisCluster().hdel(key, fields);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long hdel(String key, Iterable<String> fields) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().hdel(key, DataTypeKit.default_asStringKeyArray(fields));
        return DataTypeKit.default_returnResultLong(result);
    }

    public Set<String> hkeys(String key) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().hkeys(key);
    }

    public boolean hexists(String key, String field) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKey(field);
        Boolean result = this.jedisCluster().hexists(key, field);
        return result != null && result;
    }

    public long hlen(String key) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().hlen(key);
        return DataTypeKit.default_returnResultLong(result);
    }

    public List<Object> hvals(String key) {
        DataTypeKit.default_checkKey(key);
        List<String> values = this.jedisCluster().hvals(key);
        return DataTypeKit.default_asObjectList(values);
    }

    @Note("随机返回一个 field")
    public String hrandfield(String key) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().hrandfield(key);
    }

    @Note("随机返回 count 个 field，若 count 为正结果集不重复，为负则可重复")
    public List<String> hrandfield(String key, long count) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().hrandfield(key, count);
    }

    @Note("随机获取 count 个 hashKey-value")
    public Map<String, Object>  hrandfieldWithValues(String key, long count) {
        DataTypeKit.default_checkKey(key);
        Map<String, String> res = this.jedisCluster().hrandfieldWithValues(key, count);
        return DataTypeKit.default_asStandardMap(res);
    }

    public <T> T hrandfieldWithValuesAsJavaBean(String key, long count, C<T> javaBeanType) {
        Map<String, Object> map = this.hrandfieldWithValues(key, count);
        return (T) ObjKit.toRealValue(map, javaBeanType);
    }

    public long hstrlen(String key, String field) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKey(field);
        Long result = this.jedisCluster().hstrlen(key, field);
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("为 field 的值自增 value 个增量，如果 field 的值不存在则设置为 0，若不为字符串则抛异常")
    public long hincrBy(String key, String field, long value) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKey(field);
        Long result = this.jedisCluster().hincrBy(key, field, value);
        return DataTypeKit.default_returnResultLong(result);
    }

    public double hincrByFloat(String key, String field, double value) {
        DataTypeKit.default_checkKey(key);
        DataTypeKit.default_checkKey(field);
        Double result = this.jedisCluster().hincrByFloat(key, field, value);
        return DataTypeKit.default_returnDoubleScore(result);
    }

    @Note("游标 cursor 的初始值为【0】，当返回的游标值再度为【0】 时才代表整体遍历结束" +
            "返回值是批量的 key 和下一次开始游标。" +
            "返回的结果可能会有重复，需要自己去重")
    public ScanResult<Map.Entry<String, String>> hscan(String key, String cursor) {
        DataTypeKit.default_checkKey(key);
        if(cursor == null || cursor.isEmpty()) cursor = "0";
        return this.jedisCluster().hscan(key, cursor);
    }


    /* **********************************************************************************
     *
     *          Set 集合类型 - 操作方法
     *
     * *********************************************************************************
     * */

    public long sadd(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().sadd(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long sadd(String key, Object... values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().sadd(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long sadd(String key, Iterable values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().sadd(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }

    public boolean sismember(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Boolean result = this.jedisCluster().sismember(key, ObjKit.toStringEmptyString(value));
        return result != null && result;
    }

    public long scard(String key) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().scard(key);
        return DataTypeKit.default_returnResultLong(result);
    }

    public Set<Object> smembers(String key) {
        DataTypeKit.default_checkKey(key);
        Set<String> results = this.jedisCluster().smembers(key);
        return DataTypeKit.default_asObjectSet(results);
    }

    public <T> Set<T> smembers(String key, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> results = this.jedisCluster().smembers(key);
        return DataTypeKit.default_asSpecifyTypeSet(results, valueType);
    }

    public <T> Set<T> smembers(String key, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> results = this.jedisCluster().smembers(key);
        return DataTypeKit.default_asSpecifyTypeSet(results, valueType);
    }

    public <T> Set<T> smembers(String key, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> results = this.jedisCluster().smembers(key);
        return DataTypeKit.default_asSpecifyTypeSet(results, valueType);
    }

    public long srem(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().srem(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long srem(String key, Object... values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().srem(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long srem(String key, Iterable values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().srem(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }

    public Object spop(String key) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().spop(key);
        return ObjKit.stringToRealValue(res, true);
    }

    public <T> T spop(String key, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().spop(key);
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T spop(String key, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().spop(key);
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T spop(String key, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().spop(key);
        return (T) ObjKit.stringToRealValue(res, valueType);
    }

    public Set<Object> spop(String key, long count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().spop(key, count);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> spop(String key, long count, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().spop(key, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> spop(String key, long count, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().spop(key, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> spop(String key, long count, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().spop(key, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("将 srcKey 中的 value 移动到 tarKey 集合中去")
    public long smove(String srcKey, String tarKey, Object value) {
        DataTypeKit.default_checkKey(srcKey);
        DataTypeKit.default_checkKey(tarKey);
        Long result = this.jedisCluster().smove(srcKey, tarKey, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("随机返回一个元素")
    public Object srandmember(String key) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().srandmember(key);
        return ObjKit.stringToRealValue(res, true);
    }

    public <T> T srandmember(String key, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().srandmember(key);
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T srandmember(String key, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().srandmember(key);
        return JsonKit.toEntity(res, valueType);
    }

    public <T> T srandmember(String key, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        String res = this.jedisCluster().srandmember(key);
        return (T) ObjKit.stringToRealValue(res, valueType);
    }


    public List<Object> srandmember(String key, int count) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().srandmember(key, count);
        return DataTypeKit.default_asObjectList(res);
    }

    public <T> List<T> srandmember(String key, int count, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().srandmember(key, count);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    public <T> List<T> srandmember(String key, int count, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().srandmember(key, count);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    public <T> List<T> srandmember(String key, int count, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        List<String> res = this.jedisCluster().srandmember(key, count);
        return DataTypeKit.default_asSpecifyTypeList(res, valueType);
    }

    @Note("取多个集合的交集部分返回")
    public Set<Object> sinter(String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sinter(keys);
        return DataTypeKit.default_asObjectSet(res);
    }

    public Set<Object> sinter(Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sinter(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> sinter(Class<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sinter(keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sinter(Class<T> valueType, Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sinter(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sinter(TypeReference<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sinter(keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sinter(TypeReference<T> valueType, Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sinter(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sinter(C<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sinter(keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sinter(C<T> valueType, Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sinter(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("取多个集合的差集部分返回")
    public Set<Object> sdiff(String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sdiff(keys);
        return DataTypeKit.default_asObjectSet(res);
    }

    public Set<Object> sdiff(Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sdiff(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> sdiff(Class<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sdiff(keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sdiff(Class<T> valueType, Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sdiff(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sdiff(TypeReference<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sdiff(keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sdiff(TypeReference<T> valueType, Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sdiff(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sdiff(C<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sdiff(keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sdiff(C<T> valueType, Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sdiff(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("取多个集合的并集返回")
    public Set<Object> sunion(String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sunion(keys);
        return DataTypeKit.default_asObjectSet(res);
    }

    public Set<Object> sunion(Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sunion(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> sunion(Class<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sunion(keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sunion(Class<T> valueType, Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sunion(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sunion(TypeReference<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sunion(keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sunion(TypeReference<T> valueType, Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sunion(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sunion(C<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        Set<String> res = this.jedisCluster().sunion(keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> sunion(C<T> valueType, Iterable<String> keys) {
        Set<String> res = this.jedisCluster().sunion(DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("游标 cursor 的初始值为【0】，当返回的游标值再度为【0】 时才代表整体遍历结束" +
            "返回值是批量的 key 和下一次开始游标。" +
            "返回的结果可能会有重复，需要自己去重")
    public ScanResult<String> sscan(String key, String cursor) {
        DataTypeKit.default_checkKey(key);
        if(cursor == null || cursor.isEmpty()) cursor = "0";
        return this.jedisCluster().sscan(key, cursor);
    }

    @Note("取多个集合的差集，然后保存到 tarKey 中")
    public long sdiffstore(String tarKey, String... srcKeys) {
        DataTypeKit.default_checkKey(tarKey);
        DataTypeKit.default_checkKeys(srcKeys);
        Long result = this.jedisCluster().sdiffstore(tarKey, srcKeys);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long sdiffstore(String tarKey, Iterable<String> srcKeys) {
        DataTypeKit.default_checkKey(tarKey);
        Long result = this.jedisCluster().sdiffstore(tarKey, DataTypeKit.default_asStringKeyArray(srcKeys));
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("取多个集合的交集，然后保存到 tarKey 中")
    public long sinterstore(String tarKey, String... srcKeys) {
        DataTypeKit.default_checkKey(tarKey);
        DataTypeKit.default_checkKeys(srcKeys);
        Long result = this.jedisCluster().sinterstore(tarKey, srcKeys);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long sinterstore(String tarKey, Iterable<String> srcKeys) {
        DataTypeKit.default_checkKey(tarKey);
        Long result = this.jedisCluster().sinterstore(tarKey, DataTypeKit.default_asStringKeyArray(srcKeys));
        return DataTypeKit.default_returnResultLong(result);
    }


    @Note("取多个集合的并集保存到 tarKey 中")
    public long sunionstore(String tarKey, String... srcKeys) {
        DataTypeKit.default_checkKey(tarKey);
        DataTypeKit.default_checkKeys(srcKeys);
        Long result = this.jedisCluster().sunionstore(tarKey, srcKeys);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long sunionstore(String tarKey, Iterable<String> srcKeys) {
        DataTypeKit.default_checkKey(tarKey);
        Long result = this.jedisCluster().sunionstore(tarKey, DataTypeKit.default_asStringKeyArray(srcKeys));
        return DataTypeKit.default_returnResultLong(result);
    }


    /* **********************************************************************************
     *
     *          ZSet 有序集合类型 - 操作方法
     *
     * *********************************************************************************
     * */

    public long zadd(String key, double score, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zadd(key, score, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zadd(String key, Map<Object, Double> valueAndScores) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zadd(key, DataTypeKit.default_asStringKeyMap(valueAndScores));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zadd(String key, OwnPairs<Object, Double> valueAndScores) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zadd(key, DataTypeKit.default_asStringKeyMap(valueAndScores));
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("ZAddParams 可以设置 >、<、xx、nx 等等参数")
    public long zadd(String key, double score, Object value, ZAddParams params) {
        DataTypeKit.default_checkKey(key);
        if(params == null) return this.zadd(key, score, value);
        Long result = this.jedisCluster().zadd(key, score, ObjKit.toStringEmptyString(value), params);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zadd(String key, Map<Object, Double> valueAndScores, ZAddParams params) {
        DataTypeKit.default_checkKey(key);
        if(params == null) return this.zadd(key, valueAndScores);
        Long result = this.jedisCluster().zadd(key, DataTypeKit.default_asStringKeyMap(valueAndScores), params);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zadd(String key, OwnPairs<Object, Double> valueAndScores, ZAddParams params) {
        DataTypeKit.default_checkKey(key);
        if(params == null) return this.zadd(key, valueAndScores);
        Long result = this.jedisCluster().zadd(key, DataTypeKit.default_asStringKeyMap(valueAndScores), params);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zcard(String key) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zcard(key);
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("统计在 min ~ max 这个范围内的元素的个数")
    public long zcount(String key, double min, double max) {
        DataTypeKit.default_checkKey(key);
        Long count = this.jedisCluster().zcount(key, min, max);
        return DataTypeKit.default_returnResultLong(count);
    }

    @Note("给 value 的分值加上 incrNum 的增量")
    public double zincrby(String key, double incrNum, Object value) {
        DataTypeKit.default_checkKey(key);
        Double score = this.jedisCluster().zincrby(key, incrNum, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnDoubleScore(score);
    }

    @Note("ZIncrByParams 可以设置 xx、nx、incr 等参数")
    public double zincrby(String key, double incrNum, Object value, ZIncrByParams params) {
        DataTypeKit.default_checkKey(key);
        if(params == null) return this.zincrby(key, incrNum, value);
        Double score = this.jedisCluster().zincrby(key, incrNum, ObjKit.toStringEmptyString(value), params);
        return DataTypeKit.default_returnDoubleScore(score);
    }

    @Note("返回有序集合中指定元素的排名")
    public long zrank(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Long ranking = this.jedisCluster().zrank(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnTimeResult(ranking);
    }

    @Note("返回指定元素的排名，是由大到小递减的排名")
    public long zrevrank(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zrevrank(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }


    public long zrem(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zrem(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zrem(String key, Object... values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zrem(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zrem(String key, Iterable values) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zrem(key, DataTypeKit.default_asStringArray(values));
        return DataTypeKit.default_returnResultLong(result);
    }
    
    @Note("删除从 min 到 max 之间的所有元素")
    public long zremrangeByLex(String key, Object min, Object max) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zremrangeByLex(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max));
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("删除排名为 start 到 stop 之间的所有元素")
    public long zremrangeByRank(String key, long start, long stop) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zremrangeByRank(key, start, stop);
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("删除分数在 min 到 max 之间的所有元素")
    public long zremrangeByScore(String key, double min, double max) {
        DataTypeKit.default_checkKey(key);
        Long result = this.jedisCluster().zremrangeByScore(key, min, max);
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("返回指定 value 的分数")
    public double zscore(String key, Object value) {
        DataTypeKit.default_checkKey(key);
        Double score = this.jedisCluster().zscore(key, ObjKit.toStringEmptyString(value));
        return DataTypeKit.default_returnDoubleScore(score);
    }

    public Set<Object> zrange(String key, long start, long stop) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrange(key, start, stop);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrange(String key, long start, long stop, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrange(key, start, stop);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrange(String key, long start, long stop, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrange(key, start, stop);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrange(String key, long start, long stop, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrange(key, start, stop);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("返回有序集合中元素排名在 min 到 max 之间的所有元素")
    public Set<Object> zrangeByLex(String key, Object min, Object max) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByLex(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max));
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrangeByLex(String key, Object min, Object max, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByLex(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByLex(String key, Object min, Object max, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByLex(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByLex(String key, Object min, Object max, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByLex(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("分页的方式分批返回 min 到 max 之间的元素")
    public Set<Object> zrangeByLex(String key, Object min, Object max, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByLex(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max), offset, count);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrangeByLex(String key, Object min, Object max, Class<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByLex(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByLex(String key, Object min, Object max, TypeReference<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByLex(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByLex(String key, Object min, Object max, C<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByLex(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("返回分数在 min 到 max 之间的所有元素")
    public Set<Object> zrangeByScore(String key, double min, double max) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, min, max);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrangeByScore(String key, double min, double max, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, min, max);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByScore(String key, double min, double max, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, min, max);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByScore(String key, double min, double max, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, min, max);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("分页的方式分批返回分数在 min 和 max 之间的所有元素")
    public Set<Object> zrangeByScore(String key, double min, double max, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, min, max, offset, count);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrangeByScore(String key, double min, double max, Class<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, min, max, offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByScore(String key, double min, double max, TypeReference<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, min, max, offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByScore(String key, double min, double max, C<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, min, max, offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("返回元素排名在 min 和 max 之间的所有元素")
    public Set<Object> zrangeByScore(String key, Object min, Object max) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max));
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrangeByScore(String key, Object min, Object max, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByScore(String key, Object min, Object max, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByScore(String key, Object min, Object max, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("分页分批返回排名在 min 和 max 之间的所有元素")
    public Set<Object> zrangeByScore(String key, Object min, Object max, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max), offset, count);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrangeByScore(String key, Object min, Object max, Class<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByScore(String key, Object min, Object max, TypeReference<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrangeByScore(String key, Object min, Object max, C<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrangeByScore(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("返回分数在 min 到 max 之间的所有元素和它的分数")
    public Set<Tuple> zrangeByScoreWithScores(String key, double min, double max) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().zrangeByScoreWithScores(key, min, max);
    }

    public Set<Tuple> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().zrangeByScoreWithScores(key, min, max, offset, count);
    }

    @Note("返回元素排名在 min 到 max 之间的所有元素和它的分数")
    public Set<Tuple> zrangeByScoreWithScores(String key, Object min, Object max) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().zrangeByScoreWithScores(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max));
    }

    public Set<Tuple> zrangeByScoreWithScores(String key, Object min, Object max, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().zrangeByScoreWithScores(key, ObjKit.toStringEmptyString(min), ObjKit.toStringEmptyString(max), offset, count);
    }

    @Note("返回排名位于 start 到 stop 分值逆序的元素，逆序也就是分值从大到小")
    public Set<Object> zrevrange(String key, long start, long stop) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrange(key, start, stop);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrevrange(String key, long start, long stop, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrange(key, start, stop);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrange(String key, long start, long stop, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrange(key, start, stop);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrange(String key, long start, long stop, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrange(key, start, stop);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("返回 max 到 min 之间的元素。也就是逆序的")
    public Set<Object> zrevrangeByLex(String key, Object max, Object min) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByLex(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min));
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrevrangeByLex(String key, Object max, Object min, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByLex(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByLex(String key, Object max, Object min, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByLex(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByLex(String key, Object max, Object min, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByLex(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("分页分批返回 max 到 min 之间的元素。也就是逆序的")
    public Set<Object> zrevrangeByLex(String key, Object max, Object min, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByLex(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min), offset, count);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrevrangeByLex(String key, Object max, Object min, int offset, int count, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByLex(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByLex(String key, Object max, Object min, int offset, int count, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByLex(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByLex(String key, Object max, Object min, int offset, int count, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByLex(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("返回分数在 max 到 min 之家的所有元素，顺序是逆序的")
    public Set<Object> zrevrangeByScore(String key, double max, double min) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, max, min);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrevrangeByScore(String key, double max, double min, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, max, min);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByScore(String key, double max, double min, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, max, min);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByScore(String key, double max, double min, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, max, min);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("分页分批返回分数在 max 到 min 之家的元素，顺序是逆序的")
    public Set<Object> zrevrangeByScore(String key, double max, double min, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, max, min, offset, count);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrevrangeByScore(String key, double max, double min, Class<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, max, min, offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByScore(String key, double max, double min, TypeReference<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, max, min, offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByScore(String key, double max, double min, C<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, max, min, offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("返回在 max 到 min 之间的元素，顺序是逆序的")
    public Set<Object> zrevrangeByScore(String key, Object max, Object min) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min));
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrevrangeByScore(String key, Object max, Object min, Class<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByScore(String key, Object max, Object min, TypeReference<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByScore(String key, Object max, Object min, C<T> valueType) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("分页分批返回在 max 到 min 之间的元素，顺序是逆序的")
    public Set<Object> zrevrangeByScore(String key, Object max, Object min, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min), offset, count);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zrevrangeByScore(String key, Object max, Object min, Class<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByScore(String key, Object max, Object min, TypeReference<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zrevrangeByScore(String key, Object max, Object min, C<T> valueType, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        Set<String> res = this.jedisCluster().zrevrangeByScore(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min), offset, count);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("返回排名在 start 到 top 之间的所有元素和它们的分数返回")
    public Set<Tuple> zrangeWithScores(String key, long start, long stop) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().zrangeWithScores(key, start, stop);
    }

    @Note("返回排名在 start 到 top 之间的所有元素和它们的分数返回。但顺序是逆序的")
    public Set<Tuple> zrevrangeWithScores(String key, long start, long stop) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().zrevrangeWithScores(key, start, stop);
    }

    @Note("返回分数在 max 到 min 之间的所有元素和它们的分数")
    public Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().zrangeByScoreWithScores(key, max, min);
    }

    @Note("返回分数在 max 到 min 之间的所有元素和它们的分数")
    public Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().zrangeByScoreWithScores(key, max, min, offset, count);
    }

    @Note("返回分数在 max 到 min 之间的所有元素和它们的分数")
    public Set<Tuple> zrevrangeByScoreWithScores(String key, Object max, Object min) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().zrangeByScoreWithScores(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min));
    }

    @Note("返回分数在 max 到 min 之间的所有元素和它们的分数")
    public Set<Tuple> zrevrangeByScoreWithScores(String key, Object max, Object min, int offset, int count) {
        DataTypeKit.default_checkKey(key);
        return this.jedisCluster().zrangeByScoreWithScores(key, ObjKit.toStringEmptyString(max), ObjKit.toStringEmptyString(min), offset, count);
    }

    @Note("把多个集合的交集，然后将结果放到 targetKey 的集合中")
    public long zinterstore(String targetKey, String... srcKeys) {
        DataTypeKit.default_checkKey(targetKey);
        DataTypeKit.default_checkKeys(srcKeys);
        Long result = this.jedisCluster().zinterstore(targetKey, srcKeys);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zinterstore(String targetKey, Iterable<String> srcKeys) {
        DataTypeKit.default_checkKey(targetKey);
        Long result = this.jedisCluster().zinterstore(targetKey, DataTypeKit.default_asStringKeyArray(srcKeys));
        return DataTypeKit.default_returnResultLong(result);
    }


    @Note("把多个集合的交集，然后将结果放到 targetKey 的集合中。ZParams 有 SUM、MIN、MAX 等")
    public long zinterstore(String targetKey, ZParams params, String... srcKeys) {
        DataTypeKit.default_checkKey(targetKey);
        DataTypeKit.default_checkKeys(srcKeys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Long result = this.jedisCluster().zinterstore(targetKey, params, srcKeys);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zinterstore(String targetKey, ZParams params, Iterable<String> srcKeys) {
        DataTypeKit.default_checkKey(targetKey);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Long result = this.jedisCluster().zinterstore(targetKey, params, DataTypeKit.default_asStringKeyArray(srcKeys));
        return DataTypeKit.default_returnResultLong(result);
    }

    @Note("返回多个集合的交集，其中的元素包含了分数。ZParams 有 SUM、MIN、MAX 等")
    public Set<Tuple> zinterWithScores(ZParams params, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        return this.jedisCluster().zinterWithScores(params, keys);
    }

    public Set<Tuple> zinterWithScores(ZParams params, Iterable<String> keys) {
        DataTypeKit.default_checkZParamsIsNotNull(params);
        return this.jedisCluster().zinterWithScores(params, DataTypeKit.default_asStringKeyArray(keys));
    }

    @Note("取多个有序集合的交集，ZParams 可以设置 MIN、MAX、SUM 等关系")
    public Set<Object> zinter(ZParams params, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zinter(params, keys);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zinter(ZParams params, Class<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zinter(params, keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zinter(ZParams params, TypeReference<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zinter(params, keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zinter(ZParams params, C<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zinter(params, keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }


    public Set<Object> zinter(ZParams params, Iterable<String> keys) {
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zinter(params, DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zinter(ZParams params, Class<T> valueType, Iterable<String> keys) {
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zinter(params, DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zinter(ZParams params, TypeReference<T> valueType, Iterable<String> keys) {
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zinter(params, DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zinter(ZParams params, C<T> valueType, Iterable<String> keys) {
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zinter(params, DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    @Note("取多个集合的并集，并将其保存至 tarKey 集合中")
    public long zunionstore(String tarKey, String... srcKeys) {
        DataTypeKit.default_checkKey(tarKey);
        DataTypeKit.default_checkKeys(srcKeys);
        Long result = this.jedisCluster().zunionstore(tarKey, srcKeys);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zunionstore(String tarKey, Iterable<String> srcKeys) {
        DataTypeKit.default_checkKey(tarKey);
        Long result = this.jedisCluster().zunionstore(tarKey, DataTypeKit.default_asStringKeyArray(srcKeys));
        return DataTypeKit.default_returnResultLong(result);
    }


    @Note("取多个集合的并集，并将其保存至 tarKey 集合中。其中 ZParams 可以设置 MIN、MAX、SUM 等关系")
    public long zunionstore(String tarKey, ZParams params, String... srcKeys) {
        DataTypeKit.default_checkKey(tarKey);
        DataTypeKit.default_checkKeys(srcKeys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Long result = this.jedisCluster().zunionstore(tarKey, params, srcKeys);
        return DataTypeKit.default_returnResultLong(result);
    }

    public long zunionstore(String tarKey, ZParams params, Iterable<String> srcKeys) {
        DataTypeKit.default_checkKey(tarKey);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Long result = this.jedisCluster().zunionstore(tarKey, params, DataTypeKit.default_asStringKeyArray(srcKeys));
        return DataTypeKit.default_returnResultLong(result);
    }


    @Note("返回多个集合的并集的元素和分数")
    public Set<Tuple> zunionWithScores(ZParams params, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        return this.jedisCluster().zunionWithScores(params, keys);
    }

    public Set<Tuple> zunionWithScores(ZParams params, Iterable<String> keys) {
        DataTypeKit.default_checkZParamsIsNotNull(params);
        return this.jedisCluster().zunionWithScores(params, DataTypeKit.default_asStringKeyArray(keys));
    }

    @Note("返回多个集合的并集，ZParams 可以设置 MIN、MAX、SUM 等关系")
    public Set<Object> zunion(ZParams params, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zunion(params, keys);
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zunion(ZParams params, Class<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zunion(params, keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zunion(ZParams params, TypeReference<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        DataTypeKit.default_checkZParamsIsNotNull (params);
        Set<String> res = this.jedisCluster().zunion(params, keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zunion(ZParams params, C<T> valueType, String... keys) {
        DataTypeKit.default_checkKeys(keys);
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zunion(params, keys);
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }


    public Set<Object> zunion(ZParams params, Iterable<String> keys) {
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zunion(params, DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asObjectSet(res);
    }

    public <T> Set<T> zunion(ZParams params, Class<T> valueType, Iterable<String> keys) {
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zunion(params, DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zunion(ZParams params, TypeReference<T> valueType, Iterable<String> keys) {
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zunion(params, DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

    public <T> Set<T> zunion(ZParams params, C<T> valueType, Iterable<String> keys) {
        DataTypeKit.default_checkZParamsIsNotNull(params);
        Set<String> res = this.jedisCluster().zunion(params, DataTypeKit.default_asStringKeyArray(keys));
        return DataTypeKit.default_asSpecifyTypeSet(res, valueType);
    }

}
